본문으로 건너뛰기

Ch2. 렉시컬 스코프

스코프의 종류

  1. 렉시컬 스코프 (Lexical Scope)
  2. 동적 스코프 (Dynamic Scope)

→ JavaScript는 렉시컬 스코프를 사용한다.

function foo() {
console.log(a);
}

function bar() {
var a = 3;
foo();
}

var a = 2;
bar(); // 출력: 2 (렉시컬 기준)

2.1 렉스타임

렉시컬 스코프는 코드가 작성된 시점에 스코프가 결정된다.

function foo(a) {
var b = a * 2;
function bar(c) {
console.log(a, b, c);
}
bar(b * 3);
}

foo(2); // 2, 4, 12
  • 총 3개의 스코프 생성됨
    1. 전체 범위
    2. foo 내부
    3. bar 내부

→ 스코프는 겹치는 게 아니라 포함되는 구조 (버블 형태)


섀도잉 (Shadowing)

  • 안쪽 스코프의 변수가 바깥쪽 변수 이름을 가리는 현상
  • 전역 awindow.a로 접근 가능하긴 함

2.2 렉시컬 속이기 (스코프 위조)

렉시컬 스코프를 동적으로 바꾸는 유일한 방법:

  • eval
  • with

2.2.1 eval

function foo(str, a) {
eval(str);
console.log(a, b);
}

var b = 2;
foo("var b = 3;", 1); // 1, 3
console.log(b); // 2
  • eval은 그 자리에서 코드를 실행시켜 렉시컬 스코프를 위조함
  • strict mode에서는 자체 스코프 생성 → 바깥 영향 없음

2.2.2 with

var obj = { a: 1, b: 2, c: 3 };

with (obj) {
a = 3;
b = 4;
c = 5;
}
function foo(obj) {
with (obj) {
a = 2;
}
}

var o1 = { a: 1 };
var o2 = { b: 1 };

foo(o1); // o1.a → 2
foo(o2); // o2.a → undefined, 전역 a 생성됨!
  • with는 별도 스코프 생성
  • 동적 레퍼런스 → 성능 최적화 방해

2.2.3 성능 저하

  • eval, with은 엔진이 컴파일 시 변수 위치를 미리 예측하지 못하게 함
  • 최적화 불가 → 퍼포먼스 저하
  • 사용 지양 권장

2.3 정리

  • JavaScript는 렉시컬 스코프를 기반으로 한다
  • eval, with은 스코프를 속일 수 있지만 성능 저하 유발
  • 코드는 선언 위치에 따라 스코프가 고정된다